<?php
/*
Copyright (C) 2009 de Flotte Maxence

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
?>
<?php

class ZzPuzzleGeneration {
	
	static function generate($puzzleName) {
		$puzzleUrl = './ZzS/'.$puzzleName.'.ZzS';
		$genPuzzleUrl = './ZzS/gen/'.$puzzleName.'.php';
		
		$ZzS = file_get_contents($puzzleUrl);
		$ZzS = str_replace("\n","",$ZzS);
		$ZzS = str_replace("\r","",$ZzS);
		$php = '
$tr = new ZzTranslation(\'puZZleName\');
$title = $tr->tr('.addSlashes($puzzleName).').\' : \'.$GLOBALS[\'label_name\'];
$page =	new page("page");
$page->setTitle($title);';
		if(isSet($noStructure) and $noStructure)
			$php .=  '
$page->setNoStructure(\'true\');';
		$Cursor = 0;
		$line = 1;
		$_ZzO = array();
		$length = strlen($ZzS);
		while(($instruction = ZzPuzzleGeneration::convertInstruction($ZzS,$Cursor,$line, $length,$LastObjectCall, $_ZzO)) !== false)
		$php .= $instruction;
		$php .= 'echo $page->buildStaticpuZZle();';
		
		file_put_contents ($genPuzzleUrl,'<?php '.$php.' ?>');
	}
	
	static function convertInstruction($ZzS,&$Cursor,&$line, $length,&$LastObjectCall,&$_ZzO) {
	//On lit le type de l'instruction
	$Instruction = strtolower(ZzPuzzleGeneration::readWord($ZzS,$Cursor,$line,$length));
//echo '"'.$Instruction.'"<br/>';
	//Create
	$return = null;
	switch ($Instruction) {
		case null :
			return false; 
		case 'create' :
			//On recupère le nom de l'objet
			$Obj = strtolower(ZzPuzzleGeneration::readWord($ZzS,$Cursor,$line,$length));
			//On recupère l'addresse du fichier à inclure
			if($Obj != 'page') {
				$file2include = preg_replace('!^(.*)_(a-z0-1-)*$!','$1',$Obj);
				$file2include = str_replace('_','/',$file2include);
				}
			else
				$include = '';
			$Name = strtolower(ZzPuzzleGeneration::readWord($ZzS,$Cursor,$line,$length));
			if ($Name == 'named')
				$Name = strtolower(ZzPuzzleGeneration::readWord($ZzS,$Cursor,$line,$length));
			elseif($Name == ';' or $Name == 'and')
				$Name = $Obj;
			$return = '
'.$include.'
$'.$Name.' = new '.$Obj.'(\''.$Name.'\',$page);'."\n".'$'.$Name.'->page = $page;';
			$LastObjectCall = $Name;
			break;
		case  'add' :
			$Obj = strtolower(ZzPuzzleGeneration::readWord($ZzS,$Cursor,$line,$length));
			if($Obj == 'on') {
				$Obj = $LastObjectCall;
			}
			else {
				$WOn = strtolower(ZzPuzzleGeneration::readWord($ZzS,$Cursor,$line,$length));
				$LastObjectCall = $Obj;
			}
			$Where = strtolower(ZzPuzzleGeneration::readWord($ZzS,$Cursor,$line,$length));
			$return = '
$'.$Where.'->AddObject2(\'inner\',$'.$Obj.');'."\n";
			break;
		case 'set' :
			$WPropriety = strtolower(ZzPuzzleGeneration::readWord($ZzS,$Cursor,$line,$length));
			if($WPropriety != 'property')
				$Propriety = 'set'.$WPropriety;
			else
				$Propriety = 'set'.strtolower(ZzPuzzleGeneration::readWord($ZzS,$Cursor,$line,$length));
			$WOf = strtolower(ZzPuzzleGeneration::readWord($ZzS,$Cursor,$line,$length));
			if($WOf != 'of') {
				$Obj = $LastObjectCall;
			}
			else {
				$Obj = strtolower(ZzPuzzleGeneration::readWord($ZzS,$Cursor,$line,$length));
				$WAt = strtolower(ZzPuzzleGeneration::readWord($ZzS,$Cursor,$line,$length));
				$LastObjectCall = $Obj;
			}

			$Value = ZzPuzzleGeneration::readWord($ZzS,$Cursor,$line,$length);
			$return = '
$'.$Obj.'->'.addslashes($Propriety).'(\''.addslashes($Value).'\');';
			break;
		case 'insert' : 
			$Obj2Insert = strtolower(ZzPuzzleGeneration::readWord($ZzS,$Cursor,$line,$length));
			$WOn = strtolower(ZzPuzzleGeneration::readWord($ZzS,$Cursor,$line,$length));
			$WProperty = strtolower(ZzPuzzleGeneration::readWord($ZzS,$Cursor,$line,$length));
			$Property = strtolower(ZzPuzzleGeneration::readWord($ZzS,$Cursor,$line,$length));
			$WOf = strtolower(ZzPuzzleGeneration::readWord($ZzS,$Cursor,$line,$length));
			$Obj = strtolower(ZzPuzzleGeneration::readWord($ZzS,$Cursor,$line,$length));
			$return = '
$'.$Obj.'->AddObject2(\''.addslashes($Property).'\',$'.$Obj2Insert.');';
			break;
		case 'setconffile' :
			$obj = ZzPuzzleGeneration::readWord($ZzS,$Cursor,$line,$length);
			if(strToLower($obj) == 'of')
				$obj = $LastObjectCall = ZzPuzzleGeneration::readWord($ZzS,$Cursor,$line,$length);
			$name = ZzPuzzleGeneration::readWord($ZzS,$Cursor,$line,$length);
			if(strToLower($name) == 'at')
				$name = $LastObjectCall = ZzPuzzleGeneration::readWord($ZzS,$Cursor,$line,$length);
			$return = '
			$'.$obj.'->setConfFile(\''.$name.'\');';
			break;
		case 'comment' :
		case '#' :
			while($ZzS[$Cursor] != ';')
				$Cursor++;
			break;
		case ';' :
		case 'and' :
			break;
		default :
			echo 'Error #02:01 Instruction \''.$Instruction.'\' inconnue sur la ligne '.$line; return false; exit();
			break;
	}
	return $return;
}


	static function readWord($ZzS,&$Cursor,&$line,$length) {
		//Si c'est la fin du code
		if($Cursor >= $length) {
			return null;
		}
		//Si c'est on a un point virgule
		if($ZzS[$Cursor] == ';') {
			$Cursor++;
			$line++;
			return ';';
		}

		//Si le mot est un longstring
		if($ZzS[$Cursor] == '"') {
			$isLongString = true;
			$Cursor++;
		}
		else
			$isLongString = false;
		//Sinon on lit le mot
		$Word = null;
		while($ZzS[$Cursor] != "\n" AND $ZzS[$Cursor] != ' ' AND $ZzS[$Cursor] != ';' AND !$isLongString OR $ZzS[$Cursor] != '"' AND $isLongString) {
			$Word .= $ZzS[$Cursor];
			$Cursor++;
		}
		//Si il n'y a pas d'espace ou de \n après
		if($ZzS[$Cursor] == ' ') {
			$Cursor++;
			//$line++;
		}
		elseif($ZzS[$Cursor] == ';') {
			//echo $Cursor,'*';
			//$Cursor++;
		}
		if($isLongString)
			$Cursor++;
		//Si le mots est AND
		if(strtolower($Word) == 'and')
			return ';';
		return $Word;
	}
}

?>